//
// In order to convert some functionality to Visual C#, the Java Language Conversion Assistant
// creates "support classes" that duplicate the original functionality.  
//
// Support classes replicate the functionality of the original code, but in some cases they are 
// substantially different architecturally. Although every effort is made to preserve the 
// original architecture of the application in the converted project, the user should be aware that 
// the primary goal of these support classes is to replicate functionality, and that at times 
// the architecture of the resulting solution may differ somewhat.
//

using System;
using System.Xml;
using System.Qizx.Xml;
using System.Qizx.Api;

/// <summary>
/// Contains conversion support elements such as classes, interfaces and static methods.
/// </summary>
public class SupportClass {

    public static void Test() {
        XQuerySessionManager manager = new XQuerySessionManager(new Uri(@"C:\"));
        XQuerySession session = manager.CreateSession();
        Expression expression = session.CompileExpression(@"doc('D:\ITBooks\XBRL\Specification\XBRL 2.1\xbrl-instance-2003-12-31.xsd')//*[23]");
        ItemSequence items = expression.Evaluate();
        while (items.MoveToNextItem()) {
            Console.WriteLine(items.CurrentItem.ToString());
        }
    }

    /// <summary>
    /// Writes the exception stack trace to the received stream
    /// </summary>
    /// <param name="throwable">Exception to obtain information from</param>
    /// <param name="stream">Output sream used to write to</param>
    public static void WriteStackTrace(System.Exception throwable, System.IO.TextWriter stream) {
        stream.Write(throwable.StackTrace);
        stream.Flush();
    }

    /*******************************/
    /// <summary>
    /// Copies an array of chars obtained from a String into a specified array of chars
    /// </summary>
    /// <param name="sourceString">The String to get the chars from</param>
    /// <param name="sourceStart">Position of the String to start getting the chars</param>
    /// <param name="sourceEnd">Position of the String to end getting the chars</param>
    /// <param name="destinationArray">Array to return the chars</param>
    /// <param name="destinationStart">Position of the destination array of chars to start storing the chars</param>
    /// <returns>An array of chars</returns>
    public static void GetCharsFromString(string sourceString, int sourceStart, int sourceEnd, char[] destinationArray, int destinationStart) {
        int sourceCounter;
        int destinationCounter;
        sourceCounter = sourceStart;
        destinationCounter = destinationStart;
        while (sourceCounter < sourceEnd) {
            destinationArray[destinationCounter] = (char)sourceString[sourceCounter];
            sourceCounter++;
            destinationCounter++;
        }
    }

    /*******************************/
    /// <summary>
    /// Provides support for DateFormat
    /// </summary>
    public class DateTimeFormatManager {
        static public DateTimeFormatHashTable manager = new DateTimeFormatHashTable();

        /// <summary>
        /// Hashtable class to provide functionality for dateformat properties
        /// </summary>
        public class DateTimeFormatHashTable : System.Collections.Hashtable {
            /// <summary>
            /// Sets the format for datetime.
            /// </summary>
            /// <param name="format">DateTimeFormat instance to set the pattern</param>
            /// <param name="newPattern">A string with the pattern format</param>
            public void SetDateFormatPattern(System.Globalization.DateTimeFormatInfo format, string newPattern) {
                if (this[format] != null)
                    ((DateTimeFormatProperties)this[format]).DateFormatPattern = newPattern;
                else {
                    DateTimeFormatProperties tempProps = new DateTimeFormatProperties();
                    tempProps.DateFormatPattern = newPattern;
                    Add(format, tempProps);
                }
            }

            /// <summary>
            /// Gets the current format pattern of the DateTimeFormat instance
            /// </summary>
            /// <param name="format">The DateTimeFormat instance which the value will be obtained</param>
            /// <returns>The string representing the current datetimeformat pattern</returns>
            public string GetDateFormatPattern(System.Globalization.DateTimeFormatInfo format) {
                if (this[format] == null)
                    return "d-MMM-yy";
                else
                    return ((DateTimeFormatProperties)this[format]).DateFormatPattern;
            }

            /// <summary>
            /// Sets the datetimeformat pattern to the giving format
            /// </summary>
            /// <param name="format">The datetimeformat instance to set</param>
            /// <param name="newPattern">The new datetimeformat pattern</param>
            public void SetTimeFormatPattern(System.Globalization.DateTimeFormatInfo format, string newPattern) {
                if (this[format] != null)
                    ((DateTimeFormatProperties)this[format]).TimeFormatPattern = newPattern;
                else {
                    DateTimeFormatProperties tempProps = new DateTimeFormatProperties();
                    tempProps.TimeFormatPattern = newPattern;
                    Add(format, tempProps);
                }
            }

            /// <summary>
            /// Gets the current format pattern of the DateTimeFormat instance
            /// </summary>
            /// <param name="format">The DateTimeFormat instance which the value will be obtained</param>
            /// <returns>The string representing the current datetimeformat pattern</returns>
            public string GetTimeFormatPattern(System.Globalization.DateTimeFormatInfo format) {
                if (this[format] == null)
                    return "h:mm:ss tt";
                else
                    return ((DateTimeFormatProperties)this[format]).TimeFormatPattern;
            }

            /// <summary>
            /// Internal class to provides the DateFormat and TimeFormat pattern properties on .NET
            /// </summary>
            class DateTimeFormatProperties {
                public string DateFormatPattern = "d-MMM-yy";
                public string TimeFormatPattern = "h:mm:ss tt";
            }
        }
    }
    /*******************************/
    /// <summary>
    /// Gets the DateTimeFormat instance using the culture passed as parameter and sets the pattern to the time or date depending of the value
    /// </summary>
    /// <param name="dateStyle">The desired date style.</param>
    /// <param name="timeStyle">The desired time style</param>
    /// <param name="culture">The CultureInfo instance used to obtain the DateTimeFormat</param>
    /// <returns>The DateTimeFomatInfo of the culture and with the desired date or time style</returns>
    public static System.Globalization.DateTimeFormatInfo GetDateTimeFormatInstance(int dateStyle, int timeStyle, System.Globalization.CultureInfo culture) {
        const int NULLPATERN = -1;
        const int PATERN_1 = 0;
        const int PATERN_2 = 1;
        const int PATERN_3 = 2;
        const int PATERN_4 = 3;
        System.Globalization.DateTimeFormatInfo format = culture.DateTimeFormat;

        switch (timeStyle) {
            case NULLPATERN:
                DateTimeFormatManager.manager.SetTimeFormatPattern(format, "");
                break;

            case PATERN_1:
                DateTimeFormatManager.manager.SetTimeFormatPattern(format, format.LongTimePattern);
                break;

            case PATERN_2:
                DateTimeFormatManager.manager.SetTimeFormatPattern(format, "h:mm:ss tt zzz");
                break;

            case PATERN_3:
                DateTimeFormatManager.manager.SetTimeFormatPattern(format, "h:mm:ss tt");
                break;

            case PATERN_4:
                DateTimeFormatManager.manager.SetTimeFormatPattern(format, format.ShortTimePattern);
                break;
        }

        switch (dateStyle) {
            case NULLPATERN:
                DateTimeFormatManager.manager.SetDateFormatPattern(format, "");
                break;

            case PATERN_1:
                DateTimeFormatManager.manager.SetDateFormatPattern(format, format.LongDatePattern);
                break;

            case PATERN_2:
                DateTimeFormatManager.manager.SetDateFormatPattern(format, "MMMM d, yyy");
                break;

            case PATERN_3:
                DateTimeFormatManager.manager.SetDateFormatPattern(format, "MMM d, yyy");
                break;

            case PATERN_4:
                DateTimeFormatManager.manager.SetDateFormatPattern(format, format.ShortDatePattern);
                break;
        }

        return format;
    }



    /*******************************/
    /// <summary>
    /// Performs an unsigned bitwise right shift with the specified number
    /// </summary>
    /// <param name="number">Number to operate on</param>
    /// <param name="bits">Ammount of bits to shift</param>
    /// <returns>The resulting number from the shift operation</returns>
    public static int URShift(int number, int bits) {
        if (number >= 0)
            return number >> bits;
        else
            return (number >> bits) + (2 << ~bits);
    }

    /// <summary>
    /// Performs an unsigned bitwise right shift with the specified number
    /// </summary>
    /// <param name="number">Number to operate on</param>
    /// <param name="bits">Ammount of bits to shift</param>
    /// <returns>The resulting number from the shift operation</returns>
    public static int URShift(int number, long bits) {
        return URShift(number, (int)bits);
    }

    /// <summary>
    /// Performs an unsigned bitwise right shift with the specified number
    /// </summary>
    /// <param name="number">Number to operate on</param>
    /// <param name="bits">Ammount of bits to shift</param>
    /// <returns>The resulting number from the shift operation</returns>
    public static long URShift(long number, int bits) {
        if (number >= 0)
            return number >> bits;
        else
            return (number >> bits) + (2L << ~bits);
    }

    /// <summary>
    /// Performs an unsigned bitwise right shift with the specified number
    /// </summary>
    /// <param name="number">Number to operate on</param>
    /// <param name="bits">Ammount of bits to shift</param>
    /// <returns>The resulting number from the shift operation</returns>
    public static long URShift(long number, long bits) {
        return URShift(number, (int)bits);
    }

    /*******************************/
    /// <summary>
    /// This method works as a handler for the Control.Layout event, it arranges the controls into a container
    /// control in a rectangular grid (rows and columns).
    /// The size and location of each inner control will be calculated according the number of them in the 
    /// container.
    /// The number of columns, rows, horizontal and vertical spacing between the inner controls will are
    /// specified as array of object values in the Tag property of the container.
    /// If the number of rows and columns specified is not enought to allocate all the controls, the number of 
    /// columns will be increased in order to maintain the number of rows specified.
    /// </summary>
    /// <param name="event_sender">The container control in which the controls will be relocated.</param>
    /// <param name="eventArgs">Data of the event.</param>
    public static void GridLayoutResize(System.Object event_sender, System.Windows.Forms.LayoutEventArgs eventArgs) {
        System.Windows.Forms.Control container = (System.Windows.Forms.Control)event_sender;
        if ((container.Tag is System.Drawing.Rectangle) && (container.Controls.Count > 0)) {
            System.Drawing.Rectangle tempRectangle = (System.Drawing.Rectangle)container.Tag;

            if ((tempRectangle.X <= 0) && (tempRectangle.Y <= 0))
                throw new System.Exception("Illegal column and row layout count specified");

            int horizontal = tempRectangle.Width;
            int vertical = tempRectangle.Height;
            int count = container.Controls.Count;

            int rows = (tempRectangle.X == 0) ? (int)System.Math.Ceiling((double)(count / tempRectangle.Y)) : tempRectangle.X;
            int columns = (tempRectangle.Y == 0) ? (int)System.Math.Ceiling((double)(count / tempRectangle.X)) : tempRectangle.Y;

            rows = (rows == 0) ? 1 : rows;
            columns = (columns == 0) ? 1 : columns;

            while (count > rows * columns) columns++;

            int width = (container.DisplayRectangle.Width - horizontal * (columns - 1)) / columns;
            int height = (container.DisplayRectangle.Height - vertical * (rows - 1)) / rows;

            int indexColumn = 0;
            int indexRow = 0;

            foreach (System.Windows.Forms.Control tempControl in container.Controls) {
                int xCoordinate = indexColumn++ * (width + horizontal);
                int yCoordinate = indexRow * (height + vertical);
                tempControl.Location = new System.Drawing.Point(xCoordinate, yCoordinate);
                tempControl.Width = width;
                tempControl.Height = height;
                if (indexColumn == columns) {
                    indexColumn = 0;
                    indexRow++;
                }
            }
        }
    }


    /*******************************/
    /// <summary>
    /// This class manages array operations.
    /// </summary>
    public class ArraySupport {
        /// <summary>
        /// Compares the entire members of one array whith the other one.
        /// </summary>
        /// <param name="array1">The array to be compared.</param>
        /// <param name="array2">The array to be compared with.</param>
        /// <returns>True if both arrays are equals otherwise it returns false.</returns>
        /// <remarks>Two arrays are equal if they contains the same elements in the same order.</remarks>
        public static bool Equals(System.Array array1, System.Array array2) {
            bool result = false;
            if ((array1 == null) && (array2 == null))
                result = true;
            else if ((array1 != null) && (array2 != null)) {
                if (array1.Length == array2.Length) {
                    int length = array1.Length;
                    result = true;
                    for (int index = 0; index < length; index++) {
                        if (!(array1.GetValue(index).Equals(array2.GetValue(index)))) {
                            result = false;
                            break;
                        }
                    }
                }
            }
            return result;
        }

        /// <summary>
        /// Fills the array with an specific value from an specific index to an specific index.
        /// </summary>
        /// <param name="array">The array to be filled.</param>
        /// <param name="fromindex">The first index to be filled.</param>
        /// <param name="toindex">The last index to be filled.</param>
        /// <param name="val">The value to fill the array with.</param>
        public static void Fill(System.Array array, System.Int32 fromindex, System.Int32 toindex, System.Object val) {
            System.Object Temp_Object = val;
            System.Type elementtype = array.GetType().GetElementType();
            if (elementtype != val.GetType())
                Temp_Object = System.Convert.ChangeType(val, elementtype);
            if (array.Length == 0)
                throw (new System.NullReferenceException());
            if (fromindex > toindex)
                throw (new System.ArgumentException());
            if ((fromindex < 0) || ((System.Array)array).Length < toindex)
                throw (new System.IndexOutOfRangeException());
            for (int index = (fromindex > 0) ? fromindex-- : fromindex; index < toindex; index++)
                array.SetValue(Temp_Object, index);
        }

        /// <summary>
        /// Fills the array with an specific value.
        /// </summary>
        /// <param name="array">The array to be filled.</param>
        /// <param name="val">The value to fill the array with.</param>
        public static void Fill(System.Array array, System.Object val) {
            Fill(array, 0, array.Length, val);
        }
    }



    /*******************************/
    /// <summary>
    /// Method used to obtain the underlying type of an object to make the correct property call.
    /// The method is used when setting values to a property.
    /// </summary>
    /// <param name="tempObject">Object instance received.</param>
    /// <param name="propertyName">Property name to work on.</param>
    /// <param name="newValue">Object containing the value to assing.</param>
    /// <returns>The return value of the property assignment.</returns>
    public static System.Object SetPropertyAsVirtual(System.Object tempObject, string propertyName, System.Object newValue) {
        System.Type type = tempObject.GetType();
        System.Reflection.PropertyInfo propertyInfo = type.GetProperty(propertyName);
        propertyInfo.SetValue(tempObject, newValue, null);
        try {
            return propertyInfo.GetValue(tempObject, null);
        } catch (Exception e) {
            throw e.InnerException;
        }
    }






    /// <summary>
    /// Selects a range of text in the text box. 
    /// </summary>
    /// <param name="textContainer">The current text box.</param>
    /// <param name="start">The position of the first character in the current text selection within the text box.</param>
    /// <param name="offset">The number of characters to select.</param>
    public static void SelectText(System.Windows.Forms.TextBoxBase textContainer, int start, int offset) {
        if (offset - start < 0)
            ((System.Windows.Forms.TextBoxBase)textContainer).Select(start, 0);
        else
            ((System.Windows.Forms.TextBoxBase)textContainer).Select(start, offset - start);
    }

    /*******************************/
    /// <summary>Reads a number of characters from the current source Stream and writes the data to the target array at the specified index.</summary>
    /// <param name="sourceStream">The source Stream to read from.</param>
    /// <param name="target">Contains the array of characteres read from the source Stream.</param>
    /// <param name="start">The starting index of the target array.</param>
    /// <param name="count">The maximum number of characters to read from the source Stream.</param>
    /// <returns>The number of characters read. The number will be less than or equal to count depending on the data available in the source Stream. Returns -1 if the end of the stream is reached.</returns>
    public static System.Int32 ReadInput(System.IO.Stream sourceStream, sbyte[] target, int start, int count) {
        // Returns 0 bytes if not enough space in target
        if (target.Length == 0)
            return 0;

        byte[] receiver = new byte[target.Length];
        int bytesRead = sourceStream.Read(receiver, start, count);

        // Returns -1 if EOF
        if (bytesRead == 0)
            return -1;

        for (int i = start; i < start + bytesRead; i++)
            target[i] = (sbyte)receiver[i];

        return bytesRead;
    }

    /// <summary>Reads a number of characters from the current source TextReader and writes the data to the target array at the specified index.</summary>
    /// <param name="sourceTextReader">The source TextReader to read from</param>
    /// <param name="target">Contains the array of characteres read from the source TextReader.</param>
    /// <param name="start">The starting index of the target array.</param>
    /// <param name="count">The maximum number of characters to read from the source TextReader.</param>
    /// <returns>The number of characters read. The number will be less than or equal to count depending on the data available in the source TextReader. Returns -1 if the end of the stream is reached.</returns>
    public static System.Int32 ReadInput(System.IO.TextReader sourceTextReader, sbyte[] target, int start, int count) {
        // Returns 0 bytes if not enough space in target
        if (target.Length == 0) return 0;

        char[] charArray = new char[target.Length];
        int bytesRead = sourceTextReader.Read(charArray, start, count);

        // Returns -1 if EOF
        if (bytesRead == 0) return -1;

        for (int index = start; index < start + bytesRead; index++)
            target[index] = (sbyte)charArray[index];

        return bytesRead;
    }

    /*******************************/
    /// <summary>
    /// Converts an array of sbytes to an array of bytes
    /// </summary>
    /// <param name="sbyteArray">The array of sbytes to be converted</param>
    /// <returns>The new array of bytes</returns>
    public static byte[] ToByteArray(sbyte[] sbyteArray) {
        byte[] byteArray = null;

        if (sbyteArray != null) {
            byteArray = new byte[sbyteArray.Length];
            for (int index = 0; index < sbyteArray.Length; index++)
                byteArray[index] = (byte)sbyteArray[index];
        }
        return byteArray;
    }

    /// <summary>
    /// Converts a string to an array of bytes
    /// </summary>
    /// <param name="sourceString">The string to be converted</param>
    /// <returns>The new array of bytes</returns>
    public static byte[] ToByteArray(string sourceString) {
        return System.Text.UTF8Encoding.UTF8.GetBytes(sourceString);
    }

    /// <summary>
    /// Converts a array of object-type instances to a byte-type array.
    /// </summary>
    /// <param name="tempObjectArray">Array to convert.</param>
    /// <returns>An array of byte type elements.</returns>
    public static byte[] ToByteArray(System.Object[] tempObjectArray) {
        byte[] byteArray = null;
        if (tempObjectArray != null) {
            byteArray = new byte[tempObjectArray.Length];
            for (int index = 0; index < tempObjectArray.Length; index++)
                byteArray[index] = (byte)tempObjectArray[index];
        }
        return byteArray;
    }

    /*******************************/
    /// <summary>
    /// Receives a byte array and returns it transformed in an sbyte array
    /// </summary>
    /// <param name="byteArray">Byte array to process</param>
    /// <returns>The transformed array</returns>
    public static sbyte[] ToSByteArray(byte[] byteArray) {
        sbyte[] sbyteArray = null;
        if (byteArray != null) {
            sbyteArray = new sbyte[byteArray.Length];
            for (int index = 0; index < byteArray.Length; index++)
                sbyteArray[index] = (sbyte)byteArray[index];
        }
        return sbyteArray;
    }

    /*******************************/
    /// <summary>
    /// Executes the specified command and arguments in a separate process.
    /// </summary>
    /// <param name="cmd">Array containing the command to call and its arguments.</param>
    /// <returns>System.Diagnostics.Process instance for managing the subprocess.</returns>
    public static System.Diagnostics.Process ExecSupport(System.String[] cmd) {
        System.Diagnostics.Process returnVal;
        switch (cmd.Length) {
            case 0:
                System.Diagnostics.Process.GetCurrentProcess();
                returnVal = System.Diagnostics.Process.Start("");
                break;
            case 1:
                System.Diagnostics.Process.GetCurrentProcess();
                returnVal = System.Diagnostics.Process.Start(cmd[0]);
                break;
            default:
                string temp = "";
                for (int i = 1; i < cmd.Length; i++)
                    if (i == 1)
                        temp = cmd[i];
                    else
                        temp = temp + " " + cmd[i];
                System.Diagnostics.Process.GetCurrentProcess();
                returnVal = System.Diagnostics.Process.Start(cmd[0], temp);
                break;
        }
        return returnVal;
    }





    /*******************************/
    /// <summary>
    /// This method returns the literal value received
    /// </summary>
    /// <param name="literal">The literal to return</param>
    /// <returns>The received value</returns>
    public static long Identity(long literal) {
        return literal;
    }

    /// <summary>
    /// This method returns the literal value received
    /// </summary>
    /// <param name="literal">The literal to return</param>
    /// <returns>The received value</returns>
    public static ulong Identity(ulong literal) {
        return literal;
    }

    /// <summary>
    /// This method returns the literal value received
    /// </summary>
    /// <param name="literal">The literal to return</param>
    /// <returns>The received value</returns>
    public static float Identity(float literal) {
        return literal;
    }

    /// <summary>
    /// This method returns the literal value received
    /// </summary>
    /// <param name="literal">The literal to return</param>
    /// <returns>The received value</returns>
    public static double Identity(double literal) {
        return literal;
    }

    /*******************************/
    /// <summary>
    /// Gets the DateTimeFormat instance and date instance to obtain the date with the format passed
    /// </summary>
    /// <param name="format">The DateTimeFormat to obtain the time and date pattern</param>
    /// <param name="date">The date instance used to get the date</param>
    /// <returns>A string representing the date with the time and date patterns</returns>
    public static string FormatDateTime(System.Globalization.DateTimeFormatInfo format, System.DateTime date) {
        string timePattern = DateTimeFormatManager.manager.GetTimeFormatPattern(format);
        string datePattern = DateTimeFormatManager.manager.GetDateFormatPattern(format);
        return date.ToString(datePattern + " " + timePattern, format);
    }

    /*******************************/
    /// <summary>
    /// Creates an output file stream to write to the file with the specified name.
    /// </summary>
    /// <param name="FileName">Name of the file to write.</param>
    /// <param name="Append">True in order to write to the end of the file, false otherwise.</param>
    /// <returns>New instance of FileStream with the proper file mode.</returns>
    public static System.IO.FileStream GetFileStream(string FileName, bool Append) {
        if (Append)
            return new System.IO.FileStream(FileName, System.IO.FileMode.Append);
        else
            return new System.IO.FileStream(FileName, System.IO.FileMode.Create);
    }


    /*******************************/
    /// <summary>
    /// Sets the capacity for the specified ArrayList
    /// </summary>
    /// <param name="vector">The ArrayList which capacity will be set</param>
    /// <param name="newCapacity">The new capacity value</param>
    public static void SetCapacity(System.Collections.ArrayList vector, int newCapacity) {
        if (newCapacity > vector.Count)
            vector.AddRange(new Array[newCapacity - vector.Count]);
        else if (newCapacity < vector.Count)
            vector.RemoveRange(newCapacity, vector.Count - newCapacity);
        vector.Capacity = newCapacity;
    }



    /*******************************/
    public class TransactionManager {
        public static ConnectionHashTable manager = new ConnectionHashTable();

        public class ConnectionHashTable : System.Collections.Hashtable {
            public System.Data.OleDb.OleDbCommand CreateStatement(System.Data.OleDb.OleDbConnection connection) {
                System.Data.OleDb.OleDbCommand command = connection.CreateCommand();
                System.Data.OleDb.OleDbTransaction transaction;
                if (this[connection] != null) {
                    ConnectionProperties Properties = ((ConnectionProperties)this[connection]);
                    transaction = Properties.Transaction;
                    command.Transaction = transaction;
                    command.CommandTimeout = 0;
                } else {
                    ConnectionProperties TempProp = new ConnectionProperties();
                    TempProp.AutoCommit = true;
                    TempProp.TransactionLevel = 0;
                    command.Transaction = TempProp.Transaction;
                    command.CommandTimeout = 0;
                    Add(connection, TempProp);
                }
                return command;
            }

            public void Commit(System.Data.OleDb.OleDbConnection connection) {
                if (this[connection] != null && !((ConnectionProperties)this[connection]).AutoCommit) {
                    ConnectionProperties Properties = ((ConnectionProperties)this[connection]);
                    System.Data.OleDb.OleDbTransaction transaction = Properties.Transaction;
                    transaction.Commit();
                    if (Properties.TransactionLevel == 0)
                        Properties.Transaction = connection.BeginTransaction();
                    else
                        Properties.Transaction = connection.BeginTransaction(Properties.TransactionLevel);
                }
            }

            public void RollBack(System.Data.OleDb.OleDbConnection connection) {
                if (this[connection] != null && !((ConnectionProperties)this[connection]).AutoCommit) {
                    ConnectionProperties Properties = ((ConnectionProperties)this[connection]);
                    System.Data.OleDb.OleDbTransaction transaction = Properties.Transaction;
                    transaction.Rollback();
                    if (Properties.TransactionLevel == 0)
                        Properties.Transaction = connection.BeginTransaction();
                    else
                        Properties.Transaction = connection.BeginTransaction(Properties.TransactionLevel);
                }
            }

            public void SetAutoCommit(System.Data.OleDb.OleDbConnection connection, bool boolean) {
                if (this[connection] != null) {
                    ConnectionProperties Properties = ((ConnectionProperties)this[connection]);
                    if (Properties.AutoCommit != boolean) {
                        Properties.AutoCommit = boolean;
                        if (!boolean) {
                            if (Properties.TransactionLevel == 0)
                                Properties.Transaction = connection.BeginTransaction();
                            else
                                Properties.Transaction = connection.BeginTransaction(Properties.TransactionLevel);
                        } else {
                            System.Data.OleDb.OleDbTransaction transaction = Properties.Transaction;
                            if (transaction != null) {
                                transaction.Commit();
                            }
                        }
                    }
                } else {
                    ConnectionProperties TempProp = new ConnectionProperties();
                    TempProp.AutoCommit = boolean;
                    TempProp.TransactionLevel = 0;
                    if (!boolean)
                        TempProp.Transaction = connection.BeginTransaction();
                    Add(connection, TempProp);
                }
            }

            public System.Data.OleDb.OleDbCommand PrepareStatement(System.Data.OleDb.OleDbConnection connection, string sql) {
                System.Data.OleDb.OleDbCommand command = this.CreateStatement(connection);
                command.CommandText = sql;
                command.CommandTimeout = 0;
                return command;
            }

            public System.Data.OleDb.OleDbCommand PrepareCall(System.Data.OleDb.OleDbConnection connection, string sql) {
                System.Data.OleDb.OleDbCommand command = this.CreateStatement(connection);
                command.CommandText = sql;
                command.CommandTimeout = 0;
                return command;
            }

            public void SetTransactionIsolation(System.Data.OleDb.OleDbConnection connection, int level) {
                ConnectionProperties Properties;
                if (level == (int)System.Data.IsolationLevel.ReadCommitted)
                    SetAutoCommit(connection, false);
                else
                    if (level == (int)System.Data.IsolationLevel.ReadUncommitted)
                        SetAutoCommit(connection, false);
                    else
                        if (level == (int)System.Data.IsolationLevel.RepeatableRead)
                            SetAutoCommit(connection, false);
                        else
                            if (level == (int)System.Data.IsolationLevel.Serializable)
                                SetAutoCommit(connection, false);

                if (this[connection] != null) {
                    Properties = ((ConnectionProperties)this[connection]);
                    Properties.TransactionLevel = (System.Data.IsolationLevel)level;
                } else {
                    Properties = new ConnectionProperties();
                    Properties.AutoCommit = true;
                    Properties.TransactionLevel = (System.Data.IsolationLevel)level;
                    Add(connection, Properties);
                }
            }

            public int GetTransactionIsolation(System.Data.OleDb.OleDbConnection connection) {
                if (this[connection] != null) {
                    ConnectionProperties Properties = ((ConnectionProperties)this[connection]);
                    if (Properties.TransactionLevel != 0)
                        return (int)Properties.TransactionLevel;
                    else
                        return 2;
                } else
                    return 2;
            }

            public bool GetAutoCommit(System.Data.OleDb.OleDbConnection connection) {
                if (this[connection] != null)
                    return ((ConnectionProperties)this[connection]).AutoCommit;
                else
                    return true;
            }

            /// <summary>
            /// Sets the value of a parameter using any permitted object.  The given argument object will be converted to the
            /// corresponding SQL type before being sent to the database.
            /// </summary>
            /// <param name="command">Command object to be changed.</param>
            /// <param name="parameterIndex">One-based index of the parameter to be set.</param>
            /// <param name="parameter">The object containing the input parameter value.</param>
            public void SetValue(System.Data.OleDb.OleDbCommand command, int parameterIndex, System.Object parameter) {
                if (command.Parameters.Count < parameterIndex)
                    command.Parameters.Add(command.CreateParameter());
                command.Parameters[parameterIndex - 1].Value = parameter;
            }

            /// <summary>
            /// Sets a parameter to SQL NULL.
            /// </summary>
            /// <param name="command">Command object to be changed.</param>
            /// <param name="parameterIndex">One-based index of the parameter to be set.</param>
            /// <param name="targetSqlType">The SQL type to be sent to the database.</param>
            public void SetNull(System.Data.OleDb.OleDbCommand command, int parameterIndex, int sqlType) {
                if (command.Parameters.Count < parameterIndex)
                    command.Parameters.Add(command.CreateParameter());
                command.Parameters[parameterIndex - 1].Value = System.Convert.DBNull;
                command.Parameters[parameterIndex - 1].OleDbType = (System.Data.OleDb.OleDbType)sqlType;
            }

            /// <summary>
            /// Sets the value of a parameter using an object.  The given argument object will be converted to the
            /// corresponding SQL type before being sent to the database.
            /// </summary>
            /// <param name="command">Command object to be changed.</param>
            /// <param name="parameterIndex">One-based index of the parameter to be set.</param>
            /// <param name="parameter">The object containing the input parameter value.</param>
            /// <param name="targetSqlType">The SQL type to be sent to the database.</param>
            public void SetObject(System.Data.OleDb.OleDbCommand command, int parameterIndex, System.Object parameter, int targetSqlType) {
                if (command.Parameters.Count < parameterIndex)
                    command.Parameters.Add(command.CreateParameter());
                command.Parameters[parameterIndex - 1].Value = parameter;
                command.Parameters[parameterIndex - 1].OleDbType = (System.Data.OleDb.OleDbType)targetSqlType;
            }

            /// <summary>
            /// Sets the value of a parameter using an object.  The given argument object will be converted to the
            /// corresponding SQL type before being sent to the database.
            /// </summary>
            /// <param name="command">Command object to be changed.</param>
            /// <param name="parameterIndex">One-based index of the parameter to be set.</param>
            /// <param name="parameter">The object containing the input parameter value.</param>
            public void SetObject(System.Data.OleDb.OleDbCommand command, int parameterIndex, System.Object parameter) {
                if (command.Parameters.Count < parameterIndex)
                    command.Parameters.Add(command.CreateParameter());
                command.Parameters[parameterIndex - 1].Value = parameter;
            }

            /// <summary>
            /// This method is for such prepared statements verify if the Conection is autoCommit for assing the transaction to the command.
            /// </summary>
            /// <param name="command">The command to be tested.</param>
            /// <returns>The number of rows afected.</returns>
            public int ExecuteUpdate(System.Data.OleDb.OleDbCommand command) {
                if (!(((ConnectionProperties)this[command.Connection]).AutoCommit)) {
                    command.Transaction = ((ConnectionProperties)this[command.Connection]).Transaction;
                    return command.ExecuteNonQuery();
                } else
                    return command.ExecuteNonQuery();
            }

            /// <summary>
            /// This method Closes the connection, and if the property of autocommit is true make the comit operation
            /// </summary>
            /// <param name="command"> The command to be closed</param>		
            public void Close(System.Data.OleDb.OleDbConnection Connection) {

                if ((this[Connection] != null) && !(((ConnectionProperties)this[Connection]).AutoCommit)) {
                    Commit(Connection);
                }
                Connection.Close();
            }

            class ConnectionProperties {
                public bool AutoCommit;
                public System.Data.OleDb.OleDbTransaction Transaction;
                public System.Data.IsolationLevel TransactionLevel;
            }
        }
    }


    /*******************************/
    /// <summary>
    /// Converts the specified collection to its string representation.
    /// </summary>
    /// <param name="c">The collection to convert to string.</param>
    /// <returns>A string representation of the specified collection.</returns>
    public static string CollectionToString(System.Collections.ICollection c) {
        System.Text.StringBuilder s = new System.Text.StringBuilder();

        if (c != null) {

            System.Collections.ArrayList l = new System.Collections.ArrayList(c);

            bool isDictionary = (c is System.Collections.BitArray || c is System.Collections.Hashtable || c is System.Collections.IDictionary || c is System.Collections.Specialized.NameValueCollection || (l.Count > 0 && l[0] is System.Collections.DictionaryEntry));
            for (int index = 0; index < l.Count; index++) {
                if (l[index] == null)
                    s.Append("null");
                else if (!isDictionary)
                    s.Append(l[index]);
                else {
                    isDictionary = true;
                    if (c is System.Collections.Specialized.NameValueCollection)
                        s.Append(((System.Collections.Specialized.NameValueCollection)c).GetKey(index));
                    else
                        s.Append(((System.Collections.DictionaryEntry)l[index]).Key);
                    s.Append("=");
                    if (c is System.Collections.Specialized.NameValueCollection)
                        s.Append(((System.Collections.Specialized.NameValueCollection)c).GetValues(index)[0]);
                    else
                        s.Append(((System.Collections.DictionaryEntry)l[index]).Value);

                }
                if (index < l.Count - 1)
                    s.Append(", ");
            }

            if (isDictionary) {
                if (c is System.Collections.ArrayList)
                    isDictionary = false;
            }
            if (isDictionary) {
                s.Insert(0, "{");
                s.Append("}");
            } else {
                s.Insert(0, "[");
                s.Append("]");
            }
        } else
            s.Insert(0, "null");
        return s.ToString();
    }

    /// <summary>
    /// Tests if the specified object is a collection and converts it to its string representation.
    /// </summary>
    /// <param name="obj">The object to convert to string</param>
    /// <returns>A string representation of the specified object.</returns>
    public static string CollectionToString(System.Object obj) {
        string result = "";

        if (obj != null) {
            if (obj is System.Collections.ICollection)
                result = CollectionToString((System.Collections.ICollection)obj);
            else
                result = obj.ToString();
        } else
            result = "null";

        return result;
    }
}
